package com.lhc.config;

import com.lhc.diy.MyTokenEnhancer;
import com.lhc.diy.MyUserAuthenticationConverter;
import com.lhc.diy.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenStore;

/**
 * @Author lhc
 * @Date 2020-09-24 15:07
 **/

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    private String USER_SERVER_RESOURCE_ID = "user-server-resource-id";

    //token存储方式
    @Autowired
    private TokenStore redisTokenStore;
    @Autowired
    private TokenStore jwtTokenStore;
    //自定义查询用户
    @Autowired
    private MyUserDetailsService myUserDetailsService;

    //加密方式
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    //自定义token返回信息
    @Bean
    TokenEnhancer tokenEnhancer() {
        return new MyTokenEnhancer();
    }

    //整合加密方式和用户信息
    @Bean
    AuthenticationProvider daoAuthenticationProvider() {
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setUserDetailsService(myUserDetailsService);
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
        return daoAuthenticationProvider;
    }

    //密码模式需要这个
    @Bean
    AuthenticationManager authenticationManager() {
        return authentication -> daoAuthenticationProvider().authenticate(authentication);
    }


    //配置appId secret  回到地址  token有效期
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients
                .inMemory()
                .withClient("client_1")
                .secret(passwordEncoder().encode("secret_1"))
                .redirectUris("https://www.baidu.com/")
                .authorizedGrantTypes("password", "refresh_token", "authorization_code")
                .scopes("all")
                .resourceIds(USER_SERVER_RESOURCE_ID) //和资源服务保持一致
                .accessTokenValiditySeconds(60)
                .refreshTokenValiditySeconds(60)

                .and()

                .withClient("client_2")
                .secret(passwordEncoder().encode("secret_2"))
                .redirectUris("https://www.baidu.com/")
                .authorizedGrantTypes("password", "refresh_token", "authorization_code")
                .scopes("all")
                .resourceIds("resourceId2")
                .accessTokenValiditySeconds(36000)
                .refreshTokenValiditySeconds(36000)
        ;
    }

    //2.配置token类型
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        DefaultAccessTokenConverter defaultAccessTokenConverter = new DefaultAccessTokenConverter();
        defaultAccessTokenConverter.setUserTokenConverter(new MyUserAuthenticationConverter());
        endpoints
                .authenticationManager(authenticationManager())   //密码模式需要配置这个
                .allowedTokenEndpointRequestMethods(HttpMethod.POST, HttpMethod.GET)
                .userDetailsService(myUserDetailsService)
                .accessTokenConverter(defaultAccessTokenConverter)
                .tokenEnhancer(tokenEnhancer())
                .tokenStore(redisTokenStore)
                .reuseRefreshTokens(true)     //refresh_token是否重复使用
        ;
    }

    //3.配置权限
    @Override  //配置令牌的端点约束
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
        oauthServer
                .allowFormAuthenticationForClients() //允许表单认证
//                .tokenKeyAccess("permitAll()")      //获取密钥不需要认证
                .tokenKeyAccess("isAuthenticated()")  //获取密钥需要认证，使用单点登陆时必须配置
                .checkTokenAccess("permitAll()");   //校验token需要带入clientId和clientSecret
    }
}